﻿

using System;
using System.Linq;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Shapes;

namespace SynergyControls
{
    /// <suMMary>
    /// Use RegisterRhythmSettingsInterface() to connect to this control.
    /// </suMMary>
    [DisplayName("Rhythm Button Bar")]
    [Description("Provides rhythm pattern control")]
    [ToolboxItem(true)]
    [TemplatePart(Name = "RhythmButtonBar", Type = typeof(Canvas))]
    public class RhythmButtonBar : SettingsUpdaterBase
    {
        #region Fields
        private Canvas canvas;
        private List<Rectangle> betterButtons;
        private List<Rectangle> FirstOfBeatCache;
        private bool isready = false;
        private byte[] pattern;

        #endregion

        #region Properties
        private Label BarLabel
        {
            get { return ResourceRoot.FindName("PART_BarLabel") as Label; }
        }
        private Label PhraseLabel
        {
            get { return ResourceRoot.FindName("PART_PhraseLabel") as Label; }
        }
        private Button BtnQuickPattern
        {
            get { return ResourceRoot.FindName("PART_BtnQuickPattern") as Button; }
        }
        public int Identifier
        {
            get;
            protected set;
        }
        public int PhraseIdentifier
        {
            get;
            protected set;
        }
        public Control Owner
        {
            get;
            protected set;
        }
        public byte[] Pattern
        {
            get { return pattern; }
            set
            {
                pattern = value;
                NotifyPatternChanged("Pattern");
            }
        }
        public bool IsReady
        {
            get 
            { return isready; }
            private set { isready = value;
                NotifyPropertyChanged("IsReady"); }
        }
        public bool QuickPatIsRndm
        {
            get;
            protected set;
        }
        
        #endregion

        #region Dependency Properties

        #region ButtonOffStyle
        /// <summary>
        /// Identifies the <see cref="PeakStyle" /> dependency property. 
        /// </summary>
        private static readonly DependencyProperty ButtonOffStyleProperty = DependencyProperty.Register("ButtonOffStyle", typeof(Style), typeof(RhythmButtonBar), new PropertyMetadata());
      
        /// <summary>
        /// Gets or sets a style with which to draw the falling peaks on the spectrum analyzer.
        /// </summary>
        [Category("Common")]
        public Style ButtonOffStyle
        {
            // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
            get
            {
                return (Style)GetValue(ButtonOffStyleProperty);
            }
            set
            {
                SetValue(ButtonOffStyleProperty, value);
            }
        }
        #endregion

        #region ButtonOnStyle
        /// <summary>
        /// Identifies the <see cref="PeakStyle" /> dependency property. 
        /// </summary>
        private static readonly DependencyProperty ButtonOnStyleProperty = DependencyProperty.Register("ButtonOnStyle", typeof(Style), typeof(RhythmButtonBar), new PropertyMetadata());
              
        /// <summary>
        /// Gets or sets a style with which to draw the falling peaks on the spectrum analyzer.
        /// </summary>
        [Category("Common")]
        public Style ButtonOnStyle
        {
            // IMPORTANT: To maintain parity between setting a property in XAML and procedural code, do not touch the getter and setter inside this dependency property!
            get
            {
                return (Style)GetValue(ButtonOnStyleProperty);
            }
            set
            {
                SetValue(ButtonOnStyleProperty, value);
            }
        }
        #endregion

        #region BeatsPerMeasure
        /// <summary>
        ///  /// <suMMary>
        /// Identifies the <see cref="BeatsPerMeasure" /> dependency property. 
        /// </suMMary>
        /// </suMMary>
        public static readonly DependencyProperty BeatsPerMeasureProperty = DependencyProperty.Register("BeatsPerMeasure", typeof(int), typeof(RhythmButtonBar), new PropertyMetadata(new PropertyChangedCallback(BeatsPerMeasureChanged)));

        private static void BeatsPerMeasureChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs args)
        {
            RhythmButtonBar instance = dependency as RhythmButtonBar;
            if (instance != null)
            {
                instance.ConstructButtons(instance.canvas);
            }
        }       

        
        public int BeatsPerMeasure
        {
            get
            {
                return (int)GetValue(BeatsPerMeasureProperty);
            }
            set
            {
                SetValue(BeatsPerMeasureProperty, value);
            }
        }

        #endregion

        #region EqualsOneBeat
        /// <summary>
        ///  /// <suMMary>
        /// Identifies the <see cref="BeatsPerMeasure" /> dependency property. 
        /// </suMMary>
        /// </suMMary>
        public static readonly DependencyProperty EqualsOneBeatProperty = DependencyProperty.Register("EqualsOneBeat", typeof(int), typeof(RhythmButtonBar), new PropertyMetadata(new PropertyChangedCallback(EqualsOneBeatChanged)));

        private static void EqualsOneBeatChanged(DependencyObject dependency, DependencyPropertyChangedEventArgs args)
        {
            RhythmButtonBar instance = dependency as RhythmButtonBar;
            if (instance != null)
            {
                instance.ConstructButtons(instance.canvas);
            }
        }
        
        public int EqualsOneBeat
        {
            get
            {
                return (int)GetValue(EqualsOneBeatProperty);
            }
            set
            {
                SetValue(EqualsOneBeatProperty, value);
            }
        }

        #endregion

        #endregion

        #region Constructors

        static RhythmButtonBar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(RhythmButtonBar), new FrameworkPropertyMetadata(typeof(RhythmButtonBar)));
        }

        public RhythmButtonBar(int identifier, int phraseIdentifier, Control owner)
        {
            Identifier = identifier;
            PhraseIdentifier = phraseIdentifier;
            Owner = owner;            
        }

        #endregion Constructors

        #region Event Overrides

        public override void OnApplyTemplate()
        {
            if (betterButtons == null)
            {
                betterButtons = new List<Rectangle>();
            }   
            canvas = ResourceRoot.FindName("PART_Canvas") as Canvas;            
            ConstructButtons(canvas);
            BarLabel.Content = "Bar " + Identifier.ToString() + ',';
            PhraseLabel.Content = "Phrase " + PhraseIdentifier.ToString();
            BtnQuickPattern.Click += BtnQuickPattern_Click;
        }

        
        void rhythmsettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "EqualsOneBeat":
                    ConstructButtons(canvas);
                    break;
                case "BeatsPerMeasure":
                    ConstructButtons(canvas);
                    break;
            }
        }
        #endregion Event Overrides

        #region Private Methods

        /// <summary>
        /// construct the bar based on the current rhythm settings
        /// </summary>
        /// <param name="canvas"></param>
        private void ConstructButtons(Canvas canvas)
        {
            IsReady = false;

            bool isFirstOfItsBeat;
            if (canvas.Children.Count > 0)
                canvas.Children.Clear();

            if (betterButtons != null && betterButtons.Count > 0)
                betterButtons.Clear();

            if (BeatsPerMeasure == 0 || EqualsOneBeat == 0)
            {
                BeatsPerMeasure = 4;
                EqualsOneBeat = 4;
            }

            byte buttonstobuild = (byte)(BeatsPerMeasure * EqualsOneBeat);

            Pattern = new byte[buttonstobuild];
                    for (int i = 0; i < buttonstobuild; i++)
                    {                       
                            Pattern[i] = 0;
                    }
                canvas.Width = 24 * buttonstobuild + buttonstobuild + 2;
                canvas.Margin = new Thickness(10);
                FirstOfBeatCache = new List<Rectangle>();
                foreach (byte j in Enumerable.Range(0, buttonstobuild))
                {
                    isFirstOfItsBeat = j % BeatsPerMeasure == 0 ? true : false;
                    Rectangle b = new Rectangle();
                    b.Height = 20;
                    b.Width = 20;
                    b.VerticalAlignment = VerticalAlignment.Center;
                    b.Style = ButtonOffStyle;
                    b.Tag = new byte[] { 0, (byte)j };
                    b.Margin = new Thickness(j * (b.Width + 4) + (j + 1 * b.Width/4), ((canvas.Height/2) - b.Height/2), 0, 0);
                    
                    if (isFirstOfItsBeat == true)
                    {
                        FirstOfBeatCache.Add(b);
                        b.SetResourceReference(Shape.StrokeThicknessProperty, new Thickness(2));
                        /*
                        RotateTransform myRotateTransform = new RotateTransform(0)
                        {
                            CenterX = (b.Margin.Right * b.Margin.Right) + b.Height / 2,
                            CenterY = (b.Margin.Top * b.Margin.Top) + b.Height / 2,

                            Angle = 45,
                        };
                        b.RenderTransform = myRotateTransform;
                        */
                    }
                    canvas.Children.Add(b);
                    b.MouseDown += anyButton_Click;
                    betterButtons.Add(b);
                }

              

            }

        #endregion

        #region Event Handlers

        private void anyButton_Click(object sender, EventArgs e)
        {
            var button = (sender as Rectangle);
            byte[] Tag = (byte[])button.Tag;
            string choc = Brushes.Chocolate.ToString();
            {
                switch (Tag[0])
                {
                    case 0:
                        Tag[0] = 1;
                        Pattern[Tag[1]] = 1;
                        NotifyPatternChanged("Pattern");
                        button.Style = ButtonOnStyle;                       
                        break;
                    case 1:
                        Tag[0] = 0;
                        Pattern[Tag[1]] = 0;                        
                        NotifyPatternChanged("Pattern");                        
                        button.Style = ButtonOffStyle;                        
                        break;
                }
            }
            IsReady = true;
        }
        /// <summary>
        /// Toggles each beat 1 button to on.
        /// if random is enabled, generates a random rhythm pattern.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BtnQuickPattern_Click(object sender, RoutedEventArgs e)
        {
            if (!QuickPatIsRndm)
            {
                if (FirstOfBeatCache.Count >= 1)
                {
                    foreach (Rectangle r in FirstOfBeatCache)
                    {
                        byte[] Tag = (byte[])r.Tag;
                        if (Tag[0] != 1)
                        {
                            anyButton_Click(r, new EventArgs());
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("Random pattern is not yet implemented");
                throw new NotImplementedException();
                //return;
            }
        }
      
        #endregion

        #region Notify Pattern Changed

        public event PropertyChangedEventHandler PatternChanged;

        public void NotifyPatternChanged(String info)
        {
            if (PatternChanged != null)
            {
                PatternChanged(null, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
        
    }
}

